const { query } = require('../config/db');

/**
 * 停车场价格计算引擎
 * 基于累计天数的阶梯式收费模式
 */
class ParkingPricingEngine {

  /**
   * 计算停车费用
   * @param {number} parkingLotId - 停车场ID
   * @param {Date|string} entryTime - 入场时间
   * @param {Date|string} exitTime - 出场时间
   * @param {string} parkingType - 停车类型 ('indoor' 或 'outdoor')，默认 'indoor'
   * @returns {Promise<Object>} 价格计算结果
   */
  async calculatePrice(parkingLotId, entryTime, exitTime, parkingType = 'indoor') {
    try {
      // 获取停车场价格配置
      const pricingConfig = await this.getParkingLotPricing(parkingLotId, parkingType);

      // 根据计费类型计算时长对应的“天数”
      const isRolling = pricingConfig.type === 'rolling_24h';
      const days = isRolling
        ? this.calculateRollingDays(entryTime, exitTime)
        : this.calculateNaturalDays(entryTime, exitTime);

      // 计算累计费用（沿用同一价格结构）
      const totalAmount = this.calculateCumulativePrice(days, pricingConfig);

      // 生成计算说明
      const description = this.generatePriceDescription(days, totalAmount, pricingConfig, parkingType);

      return {
        success: true,
        parking_lot_id: parkingLotId,
        parking_type: parkingType,
        duration_days: days,
        total_amount: totalAmount,
        calculation_method: isRolling ? 'rolling_24h' : 'cumulative_daily',
        price_breakdown: {
          days: days,
          cumulative_price: totalAmount,
          description: description,
          pricing_config: pricingConfig,
          parking_type: parkingType
        }
      };

    } catch (error) {
      console.error('价格计算错误:', error);
      return {
        success: false,
        error: error.message,
        fallback_amount: this.calculateFallbackPrice(entryTime, exitTime, parkingType)
      };
    }
  }

  // 通用：毫秒转天数并进一
  naturalDayCeil(diffMs) {
    const daysDiff = diffMs / (1000 * 60 * 60 * 24);
    return Math.ceil(daysDiff);
  }

  // 24小时滚动计费：每满24小时计1天，不足按1天计
  calculateRollingDays(entryTime, exitTime) {
    const entry = new Date(entryTime);
    const exit = new Date(exitTime);
    if (isNaN(entry.getTime()) || isNaN(exit.getTime())) throw new Error('时间格式不正确');
    if (exit <= entry) throw new Error('出场时间必须晚于入场时间');
    const ms = exit.getTime() - entry.getTime();
    return this.naturalDayCeil(ms);
  }

  // 自然日算法（兼容旧命名）
  calculateNaturalDays(entryTime, exitTime) {
    const entry = new Date(entryTime);
    const exit = new Date(exitTime);
    if (isNaN(entry.getTime()) || isNaN(exit.getTime())) throw new Error('时间格式不正确');
    if (exit <= entry) throw new Error('出场时间必须晚于入场时间');
    const ms = exit.getTime() - entry.getTime();
    return this.naturalDayCeil(ms);
  }

  /**
   * 计算停车天数（不足1天按1天计算）
   * @param {Date|string} entryTime - 入场时间
   * @param {Date|string} exitTime - 出场时间
   * @returns {number} 停车天数
   */
  calculateParkingDays(entryTime, exitTime) {
    const entry = new Date(entryTime);
    const exit = new Date(exitTime);

    if (isNaN(entry.getTime()) || isNaN(exit.getTime())) {
      throw new Error('时间格式不正确');
    }

    if (exit <= entry) {
      throw new Error('出场时间必须晚于入场时间');
    }

    // 计算时间差（毫秒）
    const timeDiff = exit.getTime() - entry.getTime();

    // 转换为天数
    const daysDiff = timeDiff / (1000 * 60 * 60 * 24);

    // 向上取整，不足1天按1天计算（自然日进一法）
    return Math.ceil(daysDiff);
  }

  /**
   * 获取停车场价格配置
   * @param {number} parkingLotId - 停车场ID
   * @param {string} parkingType - 停车类型 ('indoor' 或 'outdoor')，默认 'indoor'
   * @returns {Promise<Object>} 价格配置
   */
  async getParkingLotPricing(parkingLotId, parkingType = 'indoor') {
    try {
      const parkingLotQuery = `
        SELECT id, name, price_rules
        FROM parking_lots
        WHERE id = ? AND status = 'approved'
      `;

      const result = await query(parkingLotQuery, [parkingLotId]);

      if (result.length === 0) {
        throw new Error('停车场不存在或未审核通过');
      }

      const parkingLot = result[0];

      // 解析价格规则
      let priceRules = {};
      try {
        priceRules = typeof parkingLot.price_rules === 'string'
          ? JSON.parse(parkingLot.price_rules)
          : parkingLot.price_rules || {};
      } catch (parseError) {
        console.warn(`解析停车场 ${parkingLotId} 价格规则失败:`, parseError);
        priceRules = {};
      }

      // 检查是否启用室内外分别定价
      if (priceRules.indoor_outdoor_enabled && priceRules.indoor_prices && priceRules.outdoor_prices) {
        const targetPrices = parkingType === 'outdoor' ? priceRules.outdoor_prices : priceRules.indoor_prices;

        return {
          type: priceRules.type === 'rolling_24h' ? 'rolling_24h' : 'cumulative_daily',
          daily_prices: targetPrices.daily_prices,
          daily_price_after_7: targetPrices.daily_price_after_7 || 20.00,
          parking_lot_name: parkingLot.name,
          parking_type: parkingType,
          indoor_outdoor_enabled: true
        };
      }

      // 检查是否为统一定价（支持自然日或24小时两种）
      if ((priceRules.type === 'cumulative_daily' || priceRules.type === 'rolling_24h') && priceRules.daily_prices) {
        return {
          type: priceRules.type,
          daily_prices: priceRules.daily_prices,
          daily_price_after_7: priceRules.daily_price_after_7 || 20.00,
          parking_lot_name: parkingLot.name,
          parking_type: parkingType,
          indoor_outdoor_enabled: false
        };
      }

      // 如果没有配置或使用旧格式，返回默认配置
      return this.getDefaultPricingConfig(parkingLot.name, parkingType);

    } catch (error) {
      console.error('获取停车场价格配置错误:', error);
      throw error;
    }
  }

  /**
   * 根据天数计算累计费用
   * @param {number} days - 停车天数
   * @param {Object} pricingConfig - 价格配置
   * @returns {number} 累计费用
   */
  calculateCumulativePrice(days, pricingConfig) {
    if (days <= 0) {
      return 0;
    }

    const { daily_prices, daily_price_after_7 } = pricingConfig;

    // 如果停车天数在1-7天内，直接返回对应的累计费用
    if (days <= 7) {
      const dayKey = `day_${days}`;
      return parseFloat(daily_prices[dayKey] || 0);
    }

    // 如果超过7天，计算第7天的费用加上超出天数的费用
    const day7Price = parseFloat(daily_prices.day_7 || 0);
    const extraDays = days - 7;
    const extraPrice = extraDays * parseFloat(daily_price_after_7 || 20);

    return day7Price + extraPrice;
  }

  /**
   * 生成价格计算说明
   * @param {number} days - 停车天数
   * @param {number} totalAmount - 总费用
   * @param {Object} pricingConfig - 价格配置
   * @param {string} parkingType - 停车类型
   * @returns {string} 计算说明
   */
  generatePriceDescription(days, totalAmount, pricingConfig, parkingType = 'indoor') {
    const typeText = parkingType === 'outdoor' ? '室外' : '室内';
    const modeText = pricingConfig.type === 'rolling_24h' ? '24小时计费' : '自然天计费';

    if (days <= 7) {
      return `${modeText}，${typeText}停车${days}天，累计费用${totalAmount}元`;
    }

    const day7Price = parseFloat(pricingConfig.daily_prices.day_7 || 0);
    const extraDays = days - 7;
    const dailyPriceAfter7 = parseFloat(pricingConfig.daily_price_after_7 || 20);

    return `${modeText}，${typeText}停车${days}天，前7天累计费用${day7Price}元，第8天起${extraDays}天每天${dailyPriceAfter7}元，总计${totalAmount}元`;
  }

  /**
   * 获取默认价格配置
   * @param {string} parkingLotName - 停车场名称
   * @param {string} parkingType - 停车类型
   * @returns {Object} 默认价格配置
   */
  getDefaultPricingConfig(parkingLotName = '停车场', parkingType = 'indoor') {
    return {
      type: 'cumulative_daily',
      daily_prices: {
        day_1: 20.00,
        day_2: 60.00,
        day_3: 80.00,
        day_4: 100.00,
        day_5: 120.00,
        day_6: 140.00,
        day_7: 140.00
      },
      daily_price_after_7: 20.00,
      parking_lot_name: parkingLotName,
      parking_type: parkingType,
      indoor_outdoor_enabled: false
    };
  }

  /**
   * 计算备用价格（当主要计算失败时使用）
   * @param {Date|string} entryTime - 入场时间
   * @param {Date|string} exitTime - 出场时间
   * @param {string} parkingType - 停车类型
   * @returns {number} 备用价格
   */
  calculateFallbackPrice(entryTime, exitTime, parkingType = 'indoor') {
    try {
      const days = this.calculateParkingDays(entryTime, exitTime);
      const defaultConfig = this.getDefaultPricingConfig('停车场', parkingType);
      return this.calculateCumulativePrice(days, defaultConfig);
    } catch (error) {
      console.error('备用价格计算也失败:', error);
      return 50; // 最后的备用价格
    }
  }

  /**
   * 验证价格配置的合理性
   * @param {Object} pricingConfig - 价格配置
   * @returns {Object} 验证结果
   */
  validatePricingConfig(pricingConfig) {
    const errors = [];

    if (!pricingConfig || typeof pricingConfig !== 'object') {
      errors.push('价格配置不能为空');
      return { valid: false, errors };
    }

    // 如果启用了室内外分别定价
    if (pricingConfig.indoor_outdoor_enabled) {
      const indoorValidation = this.validateSinglePricingConfig(pricingConfig.indoor_prices, '室内');
      const outdoorValidation = this.validateSinglePricingConfig(pricingConfig.outdoor_prices, '室外');

      errors.push(...indoorValidation.errors);
      errors.push(...outdoorValidation.errors);
    } else {
      // 统一价格配置验证
      const validation = this.validateSinglePricingConfig(pricingConfig);
      errors.push(...validation.errors);
    }

    return {
      valid: errors.length === 0,
      errors: errors
    };
  }

  /**
   * 验证单个价格配置的合理性
   * @param {Object} config - 单个价格配置
   * @param {string} prefix - 错误信息前缀
   * @returns {Object} 验证结果
   */
  validateSinglePricingConfig(config, prefix = '') {
    const errors = [];
    const prefixText = prefix ? `${prefix}` : '';

    if (!config || typeof config !== 'object') {
      errors.push(`${prefixText}价格配置不能为空`);
      return { valid: false, errors };
    }

    const { daily_prices, daily_price_after_7 } = config;

    if (!daily_prices || typeof daily_prices !== 'object') {
      errors.push(`${prefixText}每日价格配置不能为空`);
      return { valid: false, errors };
    }

    // 检查1-7天的价格配置
    let previousPrice = 0;
    for (let day = 1; day <= 7; day++) {
      const dayKey = `day_${day}`;
      const dayPrice = parseFloat(daily_prices[dayKey]);

      if (isNaN(dayPrice) || dayPrice < 0) {
        errors.push(`${prefixText}第${day}天价格配置无效`);
      } else if (dayPrice < previousPrice) {
        errors.push(`${prefixText}第${day}天价格不能低于第${day-1}天价格`);
      }

      previousPrice = dayPrice;
    }

    // 检查第8天起的每日价格
    const dailyPriceAfter7Value = parseFloat(daily_price_after_7);
    if (isNaN(dailyPriceAfter7Value) || dailyPriceAfter7Value < 0) {
      errors.push(`${prefixText}第8天起每日价格配置无效`);
    }

    return {
      valid: errors.length === 0,
      errors: errors
    };
  }

  /**
   * 获取默认的室内外价格配置
   * @param {string} parkingLotName - 停车场名称
   * @returns {Object} 默认的室内外价格配置
   */
  getDefaultIndoorOutdoorPricingConfig(parkingLotName = '停车场') {
    const defaultIndoorPrices = {
      daily_prices: {
        day_1: 0.00,
        day_2: 60.00,
        day_3: 80.00,
        day_4: 100.00,
        day_5: 120.00,
        day_6: 140.00,
        day_7: 140.00
      },
      daily_price_after_7: 20.00
    };

    const defaultOutdoorPrices = {
      daily_prices: {
        day_1: 0.00,
        day_2: 50.00,
        day_3: 70.00,
        day_4: 90.00,
        day_5: 110.00,
        day_6: 130.00,
        day_7: 130.00
      },
      daily_price_after_7: 18.00
    };

    return {
      type: 'cumulative_daily',
      indoor_outdoor_enabled: true,
      indoor_prices: defaultIndoorPrices,
      outdoor_prices: defaultOutdoorPrices,
      description: '室内外分别定价模式',
      parking_lot_name: parkingLotName
    };
  }

  /**
   * 检查停车场是否启用了室内外分别定价
   * @param {number} parkingLotId - 停车场ID
   * @returns {Promise<boolean>} 是否启用室内外分别定价
   */
  async isIndoorOutdoorPricingEnabled(parkingLotId) {
    try {
      const parkingLotQuery = `
        SELECT price_rules
        FROM parking_lots
        WHERE id = ? AND status = 'approved'
      `;

      const result = await query(parkingLotQuery, [parkingLotId]);

      if (result.length === 0) {
        return false;
      }

      const parkingLot = result[0];
      let priceRules = {};

      try {
        priceRules = typeof parkingLot.price_rules === 'string'
          ? JSON.parse(parkingLot.price_rules)
          : parkingLot.price_rules || {};
      } catch (parseErr) {
        console.warn('验证价格配置解析失败:', parseErr)
        return false;
      }

      return !!(priceRules.indoor_outdoor_enabled && priceRules.indoor_prices && priceRules.outdoor_prices);

    } catch (error) {
      console.error('检查室内外定价状态错误:', error);
      return false;
    }
  }
}

// 创建单例实例
const pricingEngine = new ParkingPricingEngine();

module.exports = pricingEngine;